import SparkMd5 from 'spark-md5'
import { Message } from 'element-ui'
import { isUpload } from '../api/fileupload/index'
import Axios from 'axios'
const axios = Axios.create({
  baseURL: 'http://192.168.0.20:8842/file',
  timeout: 60000
})
const RetryCountMax = 5
const CancelToken = Axios.CancelToken
axios.interceptors.response.use(async(response) => {
  if (response.status === 200) {
    return response.data
  } else {
    return response.data
  }
})
export const sliceFileUpload = {
  data() {
    return {
      md5: '',
      fileName: '',
      size: 0,
      progress: 0,
      chunkSize: 10485760,
      cancelUpload: false,
      chunkList: [],
      file: null,
      fileid: null
    }
  },
  watch: {
    cancelUpload(newVal, oldVal) {
      if (!newVal) {
        this.uploadSectionFile()
      } else {
        this.cancel && this.cancel()
        window.RetryUpload && window.clearTimeout(window.RetryUpload)
      }
    }
  },
  methods: {
    async uploadSectionFile(param) {
      this.progress = 0
      if (param) {
        this.file = param.file
        this.chunkList = this.fileSlice(this.file)
        this.md5 = await this._md5File(this.chunkList)
        this.fileName = this.file.name
        this.size = this.file.size
      }
      let { data } = await isUpload(this.md5)
      this.fileid = data.fileid
      let curIndex = 0
      if (data.status == 1) {
        Message.info('文件已经上传过')
        this.progress = 100
        return
      }
      if (data.status === 2) {
        curIndex = data.index
      }
      // const chunks = data.data
      let sizeCount = 0
      for (let i = 0; i < this.chunkList.length; i++) {
        sizeCount += this.chunkList[i].size
        if (this.cancelUpload) return
        if (i < curIndex) continue
        try {
          await this.fileUpload(this.chunkList[i], i, this.chunkList.length)
          this.progress = Math.floor((sizeCount / this.size) * 100)
        } catch (e) {
          console.log(e)
          if (e.toString().toLocaleLowerCase().indexOf('network') !== -1) {
            Message.error('网络异常,请检查网络，重新上传')
            return
          }
          Message.error('上传中断')
          return
        }
      }
      (this.progress === 0) && (this.progress = sizeCount)
    },
    fileSlice(file) {
      const files = []
      for (let i = 0; i < file.size; i += this.chunkSize) {
        const end = (i + this.chunkSize) > file.size ? file.size : i + this.chunkSize
        files.push(file.slice(i, (end > file.size) ? file.size : end))
      }
      return files
    },
    async _md5File(files) {
      const spark = new SparkMd5.ArrayBuffer()
      var fileReader
      for (var i = 0; i < files.length; i++) {
        fileReader = new FileReader()
        fileReader.readAsArrayBuffer(files[i])
      }
      return new Promise((resolve, reject) => {
        fileReader.onload = function(e) {
          spark.append(e.target.result)
          if (i === files.length) {
            resolve(spark.end())
          }
        }
      })
    },
    async fileUpload(file, index) {
      let RetryCount = 0
      let fragmd5 = await this._md5File([file])
      var form = new FormData()
      if (this.fileid) {
        form.append('fileid', this.fileid)
      }
      form.append('filesize', this.size)
      form.append('total', this.chunkList.length)
      form.append('index', index + 1)
      form.append('filename', this.fileName)
      form.append('file', file)
      form.append('filemd5', this.md5)
      form.append('fragmd5', fragmd5)
      let self = this
      const req = () => {
        return new Promise((resolve, reject) => {
          window.RetryUpload = setTimeout(() => {
            axios.post('/frag/upload', form, {
              cancelToken: new CancelToken((c) => {
                self.cancel = c
              })
            }).then(r => resolve(r)).catch(e => reject(e))
          }, RetryCount * 1000 * 10)
        })
      }
      while (RetryCount <= RetryCountMax) {
        if (this.cancelUpload) return
        try {
          await req()
          break
        } catch (e) {
          RetryCount++
          if (RetryCount > RetryCountMax) {
            throw e
          }
        }
      }
    }
  }
}
